# Chapter 12

# Working with Graphics in JavaScript

CONTENTS

- Creating Graphical Back and Forward Buttons
- Using Dynamic Images in JavaScript
  - The `images` Array
  - Preloading Images
- Replacing Images Dynamically
- Creating a Graphical Clock
- Rotating Between Advertisement Banners
- JavaScript and Client-Side Image Maps
- Using an Image Map with JavaScript
- Workshop Wrap-Up
  - Next Steps
  - Q&A

One of the most challenging-and most rewarding-uses of a programming language is creating graphic applications and games. In this chapter you'll look at some techniques you can use for graphic pages-or to add excitement to any Web page.

Now don't get too excited-JavaScript is a young language, and a simple one, so it will be quite a while before someone writes a version of DOOM in JavaScript. However, you can create uniquely dynamic Web content. JavaScript includes several features, including dynamic images, that aren't even available in Java.

You will explore some simple examples of these techniques in this chapter. For an example of a large-scale graphic application-in this case, a poker solitaire game-see Chapter 15, "Real-Life Examples III."

## Creating Graphical Back and Forward Buttons

Let's start with an ultra-simple example of graphics in JavaScript. In Chapter 5 "Accessing Window Elements as Objects," you used a simple JavaScript event handler to create back and forward buttons, which enable the user to perform the same function as the browser's arrow buttons. To improve on this idea, let's make some spiffy-looking graphic buttons.

Listing 12.1 demonstrates this technique. Notice that there are no script tags or event handlers-this is an example of calling JavaScript through a URL, which you'll see more of in Chapter 14, "Debugging JavaScript Programs."

Netscape's view of this page is shown in Figure 12.1. This could also be done with event handlers; as a matter of fact, the latest versions of JavaScript enable you to include an event handler directly within the `<IMG>` tag, without making the image a link.

Figure 12.1 : Graphical back and forward buttons on a Web page.

> Listing 12.1. (GRBACK.htm) A simple example of graphic back and forward buttons.

>     <HTML>
>     <HEAD><TITLE>Graphic Back and Forward Buttons</TITLE>
>     </HEAD>
>     <BODY>
>     <H1>Graphical Back and Forward Buttons</H1>
>     <HR>
>     This page allows you to go back or forward to pages in the history list.
>     These should be equivalent to the back and forward arrow buttons in the
>     browser's toolbar.
>     <HR>
>     <A HREF="javascript:history.back();">
>       <IMG BORDER = 0 SRC="left.gif">
>     </A>
>     <A HREF="javascript:history.forward();">
>       <IMG BORDER = 0 SRC="right.gif">
>     </A>
>     <HR>
>     </BODY>
>     </HTML>

Although this example works, it's nothing special. You can make back buttons, forward buttons, and other graphics more interactive by using dynamic images, described in the next section.

## Using Dynamic Images in JavaScript

One of the most recent, and most exciting, features added to JavaScript is the capability of dynamically changing images. This means you can create images that "magically" change; this could be used for clocks, images that change when you click them, or even simple animations.

The images in a Web page are reflected in an array, just like form elements. By modifying the properties of the array items, you can replace the image with a different one. This enables you to create dynamically changing content on the page without even using frames.

This technique isn't perfect for all applications. Before you get started, note the following limitations:

- You can only change existing images in the page-you can't add new ones or remove an image entirely.
- You can replace an image with a larger or smaller image, but this may not look good, because the text won't be reformatted to match.
- Any image you use will have to be loaded from the server; this makes this technique impractical for complicated animations or large images.

### The `images` Array

You can change images dynamically by using the `images` array. This array contains an item for each of the images defined in the page. Each image can also have a name. In the object hierarchy, each `image` object is a child of the `document` object.

Each `image` object has the following properties:

- `border` represents the `BORDER` attribute of the `<IMG>` tag; this defines whether a border is drawn around a linked image.
- `complete` is a flag that tells you whether the image has been completely loaded. This is a Boolean value (true or false).
- `height` and `width` reflect the corresponding image attributes. This is for information only; you can't change an image's size dynamically.
- `hspace` and `vspace` represent the corresponding image attributes, which define the image's placement on the page. Again, this is a read-only attribute.
- `name` is the image's name. You can define this with the `NAME` attribute in the image definition.
- `lowsrc` is the value of the `LOWSRC` attribute. This is a Netscape-specific attribute that enables you to specify a low-resolution image to be loaded before the "real" image.
- `src` is the image's source, or URL. This is the value you can change to change images dynamically.

For most purposes, the `src` attribute is the only one you'll use. However, you can also change the `lowsrc` attribute. This defines a low-resolution image to load first and will be used only when you change the `src` attribute.

The `image` object has no methods. It does have three event handlers you can use:

- The `onLoad` event occurs when the image finishes loading.
- The `onAbort` event occurs if the user aborts the page before the image is loaded.
- The `onError` event occurs if the image file is not found or is corrupt.

### Preloading Images

Although you can't add an image to the page dynamically, you can create an independent `image` object. This enables you to specify an image that will be loaded and placed in the cache, but not displayed on the page.

This may sound useless, but it's a great way to work with modem-speed connections. Once you've preloaded an image, you can replace any of the images on the page with the image-and because it's already cached, the change happens instantly.

You can cache an image by creating a new `image` object, using the `new` keyword. Here's an example:

>     Image2 = new Image();
>     Image2.src = "arrow1.gif";

Note
The `new` keyword, and its other uses for object-oriented programming, are described in Chapter 4 "Using Built-In Objects and Custom Objects."

## Replacing Images Dynamically

Here's a quick example to show off JavaScript's dynamic image feature. The HTML document in Listing 12.2 includes five images; these are some fancy pictures of numbers from one to five. By using the selection lists and the GO button, you can place a different image in any position. Figure 12.2 shows how the page looks after a few changes.

Figure 12.2 : A page that enables you to change images dynamically.

> Listing 12.2. (NEWIMAGE.htm) An example of dynamic images.

>     <HTML>
>     <HEAD><TITLE>Image Changing Example</TITLE>
>     <SCRIPT>
>     //function to change an image's URL
>     //done "the long way" for clarity
>     function ChangeImg() {
>     // current position
>        x = parseInt(document.form1.pos.selectedIndex);
>        p = parseInt(document.form1.pos.options[x].value);
>     // new image value
>        x = document.form1.newimg.selectedIndex;
>        i = document.form1.newimg[x].value
>     // change the image URL
>        document.images[p].src = i + ".gif";
>     }
>     </SCRIPT>
>     </HEAD>
>     <BODY>
>     <H1>On-the-fly Image Changing</H1>
>     <hr>
>     The JavaScript functions on this page allow the images below to be replaced
>     without reloading the page.
>     <P>
>     Select the image position to change (numbers 0 through 4), and select the image
>     to place there (numbers 1 through 5). Then press the GO button to
>     replace the image. (Notice that since all 5 images were loaded and cached
>     when you loaded this page, the change happens VERY quickly.)
>     <HR>
>     <IMG SRC="1.gif" HEIGHT="80" WIDTH="80">
>     <IMG SRC="2.gif" HEIGHT="80" WIDTH="80">
>     <IMG SRC="3.gif" HEIGHT="80" WIDTH="80">
>     <IMG SRC="4.gif" HEIGHT="80" WIDTH="80">
>     <IMG SRC="5.gif" HEIGHT="80" WIDTH="80">
>     <HR>
>     <FORM name="form1">
>     <b>Position:</b>
>     <SELECT NAME="pos">
>     <OPTION VALUE="0">0
>     <OPTION VALUE="1">1
>     <OPTION VALUE="2">2
>     <OPTION VALUE="3">3
>     <OPTION VALUE="4">4
>     </SELECT>
>     <b>New Image:</b>
>     <SELECT NAME="newimg">
>     <OPTION VALUE="1">1
>     <OPTION VALUE="2">2
>     <OPTION VALUE="3">3
>     <OPTION VALUE="4">4
>     <OPTION VALUE="5">5
>     </SELECT>
>     <INPUT TYPE="button" VALUE="GO" onClick="ChangeImg();">
>     </FORM>
>     <HR>
>     </BODY>
>     </HTML>

The work of this program is done in the `ChangeImg()` function. This function is called by the GO button. It reads the current value of the selection lists; the first specifies the image index to change, and the second specifies the new image to place there.

Notice that the images change very quickly-almost instantly. This is because all five of the images were already in the cache. If you wish to use images that are not displayed at first, you can preload them.

## Creating a Graphical Clock

As a slightly more complex example, let's create a clock that uses JavaScript to display the current time. There are many JavaScript clocks out there on the Web, but this one is unique: using the dynamic image features, it updates the time without reloading the page or a frame.

The hardest part of this task is to create the images: the digits zero through nine, a colon to separate the time, and a slash to separate the date. You won't have to do this, because we've included some appropriate images on the CD-ROM accompanying this book.

Listing 12.3 shows the HTML and JavaScript source for the clock program, and Netscape's view of it is shown in Figure 12.3.

Figure 12.3 : Netscape's output of the clock example.

> Listing 12.3. (CLOCK.htm) A graphical clock with time and date.

>     <HTML>
>     <HEAD><TITLE>Yet Another Silly JavaScript Clock</TITLE>
>     <SCRIPT>
>     //javascript clock script
>     function Clock() {
>        D = new Date();
>        hh = D.getHours();
>        mm = D.getMinutes();
>        ss = D.getSeconds();
>        yy = D.getYear();
>        mt = D.getMonth() + 1;
>        dd = D.getDate();

>     // change the digit images
>        document.images[8].src = Url(hh/10);
>        document.images[9].src = Url(hh%10);
>        document.images[11].src = Url(mm/10);
>        document.images[12].src = Url(mm%10);
>        document.images[14].src = Url(ss/10);
>        document.images[15].src = Url(ss%10);

>     // time above, date below
>        document.images[0].src = Url(mt/10);
>        document.images[1].src = Url(mt%10);
>        document.images[3].src = Url(dd/10);
>        document.images[4].src = Url(dd%10);
>        document.images[6].src = Url(yy/10);
>        document.images[7].src = Url(yy%10);

>     // set timeout for next time (half second)
>        window.setTimeout("Clock()",500);
>     }

>     // converts 4 (numeric) to "c4.gif"
>     function Url(num) {
>     num = Math.floor(num);
>     return "c" + num + ".gif";

>     }
>     </SCRIPT>
>     </HEAD>
>     <BODY onLoad="window.setTimeout('Clock();',3000)">
>     <H1>A Graphical Clock in JavaScript</H1>
>     <hr>
>     This clock uses JavaScript's images[] array to update the time every half
>     second. It uses the current local time from the client computer. The images
>     below are dynamically replaced with the current time.
>     <HR>
>     <img src="c6.gif" HEIGHT=20 WIDTH=15><img src="c7.gif" HEIGHT=20 WIDTH=15>
>     <img src="slash.gif" HEIGHT=20 WIDTH=13><img src="c8.gif" HEIGHT=20 WIDTH=15>
>     <img src="c9.gif" HEIGHT=20 WIDTH=15><img src="slash.gif" HEIGHT=20 WIDTH=13>
>     <img src="c0.gif" HEIGHT=20 WIDTH=15><img src="c0.gif" HEIGHT=20 WIDTH=15>
>     <img src="c0.gif" HEIGHT=20 WIDTH=15><img src="c1.gif" HEIGHT=20 WIDTH=15>
>     <img src="colon.gif" HEIGHT=20 WIDTH=9><img src="c2.gif" HEIGHT=20 WIDTH=15>
>     <img src="c3.gif" HEIGHT=20 WIDTH=15><img src="colon.gif" HEIGHT=20 WIDTH=9>
>     <img src="c4.gif" HEIGHT=20 WIDTH=15><img src="c5.gif" HEIGHT=20 WIDTH=15>
>     <HR>
>     Note: The clock doesn't start updating until the page (including the images) loads.
>     The initial time and date value uses all 10 digits, so they will be cached for
>     fast updates.
>     <HR>
>     </BODY>
>     </HTML>

Let's take a look at how this program works:

- When the page first loads, the date and time are set to a bogus value that includes all the digits-as you may have guessed, this is so they'll all end up in the cache.
- An `onLoad()` event handler is used in the document body to begin updating the time three seconds after the page loads. This gives all the images time to load.
- The `Clock()` function does the actual work. This function is called by a timeout every half-second, because there's no way to call it each time the time changes. This function reads the current time and changes the images in the document for each digit.
- An extra function, `Url()`, converts numeric values to complete URLs for the image graphics.

## Rotating Between Advertisement Banners

If you've browsed the Web at all in the last year, I'm sure you noticed the advertising banners at the top of many Web pages, encouraging you to visit another page. Opinions are mixed about Web advertising, but with the commercialization of the Web, it was bound to happen.

At risk of making Web advertisements even more annoying (or more exciting, depending on your attitude) here's another application for dynamic images. You'll include an advertisement banner on a page and use JavaScript to replace it every few seconds with a new banner.

This could be used to display different banners, in the hope of catching the user's eye. You could also use this technique to rotate between different sponsors. This example uses JavaScript to change the banners and also to link to the appropriate sponsor when a banner is clicked.

For the moment, it simply displays a dialog indicating the appropriate sponsor when the banner is clicked. The end result of this idea is shown in Listing 12.4, and the output is shown in Figure 12.4.

Figure 12.4 : Netscape's output of the advertising banner example.

> Listing 12.4. (ADVERTS.htm) Using JavaScript to rotate advertisement banners.

>     <HTML>
>     <HEAD>
>     <TITLE>Rotating Advertisements</TITLE>
>     </HEAD>
>     <SCRIPT LANGUAGE="JavaScript">
>     // global variable for current sponsor
>     var sponsor = 1;

>     // function to link to appropriate sponsor
>     // (for demonstration, displays a dialog instead)
>     function GoSponsor() {
>        window.alert("Sponsor number to link to:" + sponsor);
>     }

>     // function to rotate image (currently uses 3 images)
>     function rotate() {
>        if (++sponsor > 3)  sponsor = 1;
>        document.images[0].src = "banner" + sponsor + ".gif";
>        window.setTimeout('rotate();',5000);
>     }
>     </SCRIPT>
>     <BODY onLoad="window.setTimeout('rotate();',5000);">
>     <h1>Rotating Advertisement Banners</h1>
>     <hr>
>     <A HREF="javascript:GoSponsor();">
>     <IMG NAME="banner" SRC="banner1.gif">
>     </A>
>     <hr>
>     The image above is being rotated between three different graphics. Clicking
>     on a banner will send you to the banner's corresponding sponsor. (For this
>     example, clicking will simply display a message in a dialog.)
>     <hr>

>     </BODY>
>     </HTML>

This program uses two functions:

- The `rotate()` function switches to a new banner every five seconds. The `sponsor` variable stores the current sponsor.
- The `GoSponsor()` function is called when the banner is clicked. Currently, it displays a dialog indicating the sponsor. In a real-world application, you could use a series of `if` statements to link to the appropriate sponsor by changing the `window.location` value.

Tip
You might be tempted to speed up the timer in this example and use it for animation. This will work, but only if you preload each image first. In addition, JavaScript animations aren't very fast. You may want to look into GIF animations, which provide a good alternative. See appendix C, "Online JavaScript Resources," for more information

## JavaScript and Client-Side Image Maps

A common use for graphics on the Web is in image maps-large images with clickable areas. Each area can link to a separate page. There are two types of image maps:

- `Server-side image maps` require a CGI script to interpret the user's actions.
- `Client-side image maps` are embedded in HTML, and require no interaction with the server. This is a newer standard and not officially part of HTML, but it is supported by most browsers.

You may have already guessed that JavaScript can't work with server-side image maps, because it has no link to the server. However, client-side image maps and JavaScript work well together.

You can use client-side image maps with JavaScript in three ways:

- As with any link, you can link areas of the map to `javascript:` method URLs to execute functions.
- Each `<AREA>` tag, which defines a clickable area, can have event handlers: `onMouseOver`, `onMouseOut`, and `onClick`. These function in the same way as the corresponding link and image event handlers.
- Each `<AREA>` tag is reflected in an `area` object. These objects are part of the `links` array, and have the same properties.

## Using an Image Map with JavaScript

As an example of using a client-side image map with JavaScript, let's create a simple image map menu for a fictional company. (The company's name isn't important, but it's obviously not a graphic design company.)

To create a client-side map, you need to do two things:

- Use your favorite graphics application to create the actual graphic as a GIF or JPEG image.
- Create a MP definition that describes areas in the image.
- Include the image in the document, using the `USEMAP` attribute to point to the map definition.

Note
Several shareware programs enable you to create image maps without hassle. One of them, Map This!, is included on the CD-ROM accompanying this book.

Listing 12.5 shows the example client-side image map definition. This uses both `javascript:` links and event handlers to perform functions. Rather than link to an actual page, clicking on the areas will display a message in a text field (see Figure 12.5). In addition, the `onMouseOver` event handlers display a description in the status line for each area.

Figure 12.5 : An example of an image map in JavaScript.

> Listing 12.5. (IMAGEMAP.htm) Using a client-side image map with JavaScript.

>     <HTML>
>     <HEAD>
>     <TITLE>Image Map Example</TITLE>
>     <SCRIPT LANGUAGE="JavaScript">
>     function update(text) {
>        document.form1.text1.value = text;
>     }
>     </SCRIPT>
>     </HEAD>
>     <BODY>
>     <MAP NAME="map1">
>     <AREA SHAPE=RECT COORDS="14,15,151,87" HREF="javascript:update('service');"
>      onMouseOver="window.status='Service Department'; return true;">
>     <AREA SHAPE=RECT COORDS="162,16,283,85" HREF="javascript:update('sales');"
>      onMouseOver="window.status='Sales Department'; return true;">
>     <AREA SHAPE=RECT COORDS="294,15,388,87" HREF="javascript:update('info');"
>      onMouseOver="window.status='Information'; return true;">
>     <AREA SHAPE=RECT COORDS="13,98,79,178" HREF="javascript:update('email');"
>      onMouseOver="window.status='Email Us'; return true;">
>     <AREA SHAPE=RECT COORDS="92,97,223,177" HREF="javascript:update('products');"
>      onMouseOver="window.status='Products'; return true;">
>     <AREA SHAPE=RECT COORDS="235,98,388,177" HREF="javascript:update('our staff');"
>      onMouseOver="window.status='Our Staff'; return true;">
>     <AREA SHAPE=default HREF="javascript:update('No item selected.');"
>      onMouseOver="window.status='Please select an item.'; return true;">
>     </MAP>
>     <h1>Client-Side Image Map Example</h1>
>     <hr>
>     The image map below uses JavaScript functions in each of its areas. Moving over
>     an area will display information about it in the status line. Clicking on an area
>     places the name of the area in the text field below the image map.
>     <hr>
>     <IMG SRC="imagemap.gif" USEMAP="#map1">
>     <hr>
>     <FORM NAME="form1">
>     <b>Clicked Item:</b>
>     <INPUT TYPE="text" NAME="text1" VALUE="Please select an item.">
>     </FORM>
>     <hr>
>     </BODY>
>     </HTML>

This program uses a single JavaScript function called `update()`; this function simply places an item in the text field `form1.text1`. The text is sent directly by the link in each area definition.

## Workshop Wrap-Up

In this chapter, you explored several uses of JavaScript in working with graphics, and you learned the following:

- How to create graphic back and forward buttons
- How to use the dynamic images technique to change images "on the fly"
- Applications of dynamic images, including a clock and a method for rotating advertisements
- How to use JavaScript with client-side image maps

### Next Steps

You should now understand how JavaScript works with images. Continue with one of the following:

- To review the rest of the objects in the object hierarchy, see Chapter 5 "Accessing Window Elements as Objects."
- To add more multimedia features, such as sound and video, see Chapter 13, "Working with Multimedia and Plug-Ins."
- To learn techniques for debugging JavaScript programs and review the differences between browser versions, see Chapter 14, "Debugging JavaScript Programs."
- For an example of a complete graphical application in JavaScript, see Chapter 15, "Real-Life Examples III."

### Q&A

Q: | I need to eliminate an image entirely, rather than changing its source. Is there a way to do this?
A: | Not officially; you can't remove an image. However, you can replace it with a blank image of the same size, which should produce the same effect-and a one-color GIF is a very small file. Remember, you can't do anything that would change the layout of the text.
Q: | I created a JavaScript program on a page with images, and my event handlers don't seem to be working. What's wrong?
A: | JavaScript requires you to use `HEIGHT` and `WIDTH` attributes on all `IMG` tags. Adding these will most likely make the event handlers work properly. See Chapter 14 for other debugging techniques.
Q: | I'd like to create a clock using text instead of graphics. This should be easy, right?
A: | It's easy, but only if you use a text field in a form. As for normal text in the page, there's no way to change it. You could keep the clock in a separate frame, though, and update the entire frame. An example in Chapter 9 "Using Frames, Cookies, and Other Advanced Features," does exactly `hat.